/*	$Id: log.h 1116 2010-12-12 20:56:04Z phrakt $	*/
/*
 * Copyright (c) 2003 Jean-Francois Brousseau <phrakt@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#ifndef _CANOPY_LOG_H_
#define _CANOPY_LOG_H_

#include <sys/types.h>

#include <stdarg.h>

#include <canopy/cdefs.h>

/* logging priority levels */
enum cnp_log_pri {
	CNP_LOG_TRACE,
	CNP_LOG_DEBUG,
	CNP_LOG_INFO,
	CNP_LOG_NOTICE,
	CNP_LOG_WARN,
	CNP_LOG_WARNING = CNP_LOG_WARN,
	CNP_LOG_ERR,
	CNP_LOG_ERROR = CNP_LOG_ERR,
	CNP_LOG_ERRNO,
	CNP_LOG_CRIT
};


typedef struct cnp_log_chan  cnp_log_t;
typedef enum cnp_log_pri     cnp_logpri_t;
typedef int                  cnp_logmask_t;


/*
 * The following macros are used to manipulate log masks.  A mask is just a
 * bit-field, starting with the LSB at index 0.  If the bit whose index is
 * equal to a priority level's integer value is set to 1, messages with that
 * priority level will be blocked.
 *
 * CNP_LOG_NOMASK is a useful shortcut to specify to a function that no
 * masking should be applied.
 *
 * CNP_LOG_CLRMASK() clears the log mask <m>.  No priority levels are blocked
 * when a mask is clear.
 *
 * CNP_LOG_MASKALL() fills the log mask <m>.  A full mask blocks all priority
 * levels.
 *
 * CNP_LOG_MASKPRI() masks the priority level <l> in the log mask <m>.
 *
 * CNP_LOG_UNMASKPRI() unmasks the priority level <l> in the log mask <m>.
 *
 * CNP_LOG_ISMASKED() can be used to test whether the priority level <l> is
 * masked in the log mask <m>.
 *
 */
#define CNP_LOG_NOMASK		(cnp_logmask_t)0

#define CNP_LOG_CLRMASK(m)	(m = 0)
#define CNP_LOG_MASKALL(m)	(m = ~0)
#define CNP_LOG_MASKPRI(m, l)	(m |= (1 << l))
#define CNP_LOG_UNMASKPRI(m, l)	(m &= ~(1 << l))
#define CNP_LOG_ISMASKED(m, l)	(m & (1 << l))



/*
 * The cnp_log_msg structure is used to dispatch a log message to the
 * handlers that are registered for that channel.  The <msg_string> field
 * is a dynamically-allocated string containing the formatted message itself.
 * The <msg_priority> field specifies the level of priority that was
 * attached to the message.  Each message is timestamped and the value is
 * kept in the <msg_time> field.  The <msg_chan> field is a back-pointer to
 * the channel on which the log message was written.
 */

struct cnp_log_msg {
	char            *msg_string;
	cnp_logpri_t     msg_priority;
	struct timeval   msg_time;
	cnp_log_t       *msg_chan;
};


typedef void (*cnp_loghdlr_t)(struct cnp_log_msg *, void *);


extern const char *cnp_log_pri_names[];


/* logging facility */
int        cnp_log_init    (void);
cnp_log_t* cnp_log_open    (const char *, int, cnp_logmask_t);
void       cnp_log_getmask (cnp_log_t *, cnp_logmask_t *);
void       cnp_log_setmask (cnp_log_t *, cnp_logmask_t);
void       cnp_log_close   (cnp_log_t *);
int        cnp_log_addhdlr (cnp_log_t *, cnp_logmask_t, cnp_loghdlr_t, void *);
int        cnp_log_rmhdlr  (cnp_log_t *, cnp_loghdlr_t);
void       cnp_log         (cnp_log_t *, cnp_logpri_t, const char *, ...)
				ATTR_FORMAT(3, 4);
void       cnp_vlog        (cnp_log_t *, cnp_logpri_t, const char *, va_list)
				ATTR_FORMAT(3, 0);


#define cnp_log_trace(c, ...)   cnp_log(c, CNP_LOG_TRACE, __VA_ARGS__)
#define cnp_log_debug(c, ...)   cnp_log(c, CNP_LOG_DEBUG, __VA_ARGS__)
#define cnp_log_info(c, ...)    cnp_log(c, CNP_LOG_INFO, __VA_ARGS__)
#define cnp_log_notice(c, ...)  cnp_log(c, CNP_LOG_NOTICE, __VA_ARGS__)
#define cnp_log_warn(c, ...)    cnp_log(c, CNP_LOG_WARN, __VA_ARGS__)
#define cnp_log_err(c, ...)     cnp_log(c, CNP_LOG_ERR, __VA_ARGS__)
#define cnp_log_errno(c, ...)   cnp_log(c, CNP_LOG_ERRNO, __VA_ARGS__)
#define cnp_log_crit(c, ...)    cnp_log(c, CNP_LOG_CRIT, __VA_ARGS__)

#endif /* _CANOPY_LOG_H_ */
